<?php

namespace app\mini\controller;

use app\admin\model\Goods;
use app\company\model\CompanyGoodsRule;
use app\company\model\CompanyGoodsStore;
use app\company\model\CompanyOrderDetail;
use app\company\model\StoreSalesmanOrder;
use app\company\model\StoreSalesmanOrderLog;
use app\company\model\StoreSupplier;
use app\company\model\StoreUser;
use app\company\model\CompanyOrderStorage;
use app\mini\job\order\Overtime;
use app\mini\model\Store;
use app\mini\model\StoreOrderLog;
use app\mini\model\StoreUserAccountDetail;
use app\mini\validate\StoreOrderValidate;
use app\mini\model\StoreCart;
use app\mini\model\StoreOrder as StoreOrderModel;
use app\mini\model\CompanyGoodsChangeLog;
use Exception;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use app\mini\model\StoreOrderDetail;
use think\facade\Cache;
use think\facade\Queue;
use think\Response;
use WePayV3\Order;
use app\mini\model\StoreUserCredit;
use app\company\model\StoreOrder as CompanyStoreOrderModel;
use app\mini\model\CompanyGoods;

class StoreOrder extends Base
{
    //执行顺序:
    //1.购物车页面结算/或者商品详情立即购买 跳转到结算台,
    //2.结算台点击支付生成订单并扣减库存,
    //3.这时候前端应该跳转到支付页面,
    //4.用户输入密码提交支付(微信支付) 其他支付方式(弹窗形式 确认订单)
    //5.目前没有优惠券, 后期优惠券逻辑可以添加在结算台 订单表增加 实际支付金额
    //模型
    private StoreOrderModel $model;

    //商品/数量
    protected array $goodsArray = [];

    //商品规格key
    protected string $goodsRuleKey;

    //用户id
    protected int $store_user_id = 0;

    //店铺id
    protected int $store_id = 0;


    public function initialize()
    {
        parent::initialize();
        $this->model         = new StoreOrderModel();
        $this->validateClass = StoreOrderValidate::class;
        $this->goodsRuleKey  = kcGoodsRuleKey() . $this->company_id;
        $this->store_user_id = $this->user_id;
        $this->store_id      = $this->userInfo->store_id;
    }


    public function list($order_status = 0): Response
    {
        $model = $this->model;
        if ($this->userInfo->is_salesman == 1) {
            $model = $model->salesman($this->user_id);
        } else {
            // $model = $model->user($this->user_id);
            // 这步是在进行合并订单，在门店负责人端也需要看到业务员帮此门店下单的订单
            $model = $model->whereOr([
                [
                    ['store_user_id', '=', $this->user_id],
                ],
                [
                    ['store_id', '=', $this->store_id],
                ],
            ]);
        }
        $list = $model->orderStatus($order_status)
                      ->order('id desc')
                      ->field('id,store_id,no,order_status,salesman_id')
                      ->paginate(10)
                      ->each(function ($item) {
                          $field = 'id,goods_id,goods_rule_id,quantity,amount,is_send';
                          //明细
                          $item->store_order_detail = $item->storeOrderDetails()
                                                           ->field($field)
                                                           ->select()
                                                           ->each(function ($key) use($item){
                                                               $key->goods_name = $key->goods()
                                                                                      ->withTrashed()
                                                                                      ->value('name') . $key->goodsRule()
                                                                                                            ->withTrashed()
                                                                                                            ->value('spec_name');
                                                               $key->goods_img  = $key->goodsRule()
                                                                                      ->withTrashed()
                                                                                      ->value('img');
                                                                
                                                                $changeLog = CompanyGoodsChangeLog::field('old_money')
                                                                            ->where('store_id', $item->store_id)
                                                                            ->where('goods_rule_id', $key->goods_rule_id)
                                                                            ->where('store_user_id', $this->user_id)
                                                                            ->order('id desc')
                                                                            ->find();
                                                                if($changeLog){
                                                                    $key->old_money = $changeLog['old_money'];
                                                                }
                                                           });
                          $item->total_quantity     = $item->storeOrderDetails()
                                                           ->sum('quantity');           //总件数
                          $item->total_amount       = bcadd($item->storeOrderDetails()
                                                                 ->sum('amount'), 0, 2);//总金额
                          $item->salesman           = "";                               //销售员
                          if ($item->salesman_id) {
                              $item->salesman = StoreUser::where('id', $item->salesman_id)
                                                         ->value('real_name');
                          }
                          $item->store = Store::where('id', $item->store_id)->find();
                      })
                      ->append(['store_order_status_text']);
        return $this->success('获取成功', compact('list'));
    }

    /**
     * 取消订单
     * @param $order_id
     * @return Response
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function cancel($order_id): Response
    {
        $order = CompanyStoreOrderModel::where('id', $order_id)
                                       ->find();
        if (!$order) return $this->error('订单不存在');
        try {
            $order->order_status = request()->param('order_status', 5);
            $order->save();
        } catch (Exception $e) {
            return $this->error($e->getMessage());
        }
        return $this->success('取消成功');
    }

    /**
     * 当是销售员时获取销售员门店
     * @return Response
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getSalesmanStore(): Response
    {
        $field = "id,name,is_on_credit";
        $list  = Store::where('salesman_id', $this->user_id)
                      ->withSearch('name', request()->param())
                      ->field($field)
                      ->select();
        return $this->success('获取成功', compact('list'));
    }

    /**
     * 结算并生成订单
     * @return Response
     */
    public function settlement(): Response
    {
        $this->model->startTrans();
        try {
            $this->addOrder()
                 ->addOrderDetail();                               //添加订单
            updateGoodsStock($this->goodsArray, $this->company_id);//Redis 扣减库存
            //构建微信下单
            $result = [];
            if (request()->param('pay_type', 0) == 2) {
                //微信支付配置
                $config = getWxConfig(['appid' => $this->appid]);
                // 4. 组装支付参数
                $total  = $this->model->storeOrderDetails()
                                      ->sum('amount') * 100;
                $result = Order::instance($config)
                               ->create('jsapi', [
                                   'appid'        => $config['appid'],
                                   'mchid'        => $config['mch_id'],
                                   'description'  => '商品描述',//商品描述
                                   'out_trade_no' => $this->model->no,//订单号
                                   'notify_url'   => config('platform.notify_url'),//回调地址
                                   //用户openid 唯一标识
                                   'payer'        => ['openid' => $this->userInfo->storeUserOauths()
                                                                                 ->where('oauth_type', 1)
                                                                                 ->value('oauth_id')],
                                   'amount'       => ['total' => (int)$total, 'currency' => 'CNY'],//total 总金额 单位分
                               ]);
            }
            $order_id = $this->model->id;
            //延迟队列 10分钟后未支付自动取消订单
            Queue::later(config('queue.order.overtime'), Overtime::class, ["order_id" => $this->model->id], "overtime");
            $this->model->commit();
            return $this->success('下单成功', compact('result', 'order_id'));
        } catch (Exception $e) {
            $this->model->rollback();
            return $this->error($e->getMessage());
//            return $this->error('下单失败');
        }
    }

    /**
     * 确认收货
     * @param $order_id
     * @return Response
     */
    public function confirm($order_id): Response
    {
        $this->model->startTrans();
        try {
            //1. 验证订单
            if (!$orderModel = CompanyStoreOrderModel::find($order_id)) exception('订单不存在');
            //3. 修改订单状态
            $orderModel->order_status = request()->param('order_status', 4);
            $orderModel->save();
            $this->model->commit();
            return $this->success('确认收货成功');
        } catch (Exception $e) {
            $this->model->rollback();
            return $this->error($e->getMessage());
        }
    }


    /**
     * 订单详情
     * @param $order_id
     * @return Response
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function detail($order_id): Response
    {
        //1. 验证订单
        if (!$orderModel =
            $this->model->field('id,store_id,no,pay_type,order_status,store_user_id,create_time,voucher,store_id,salesman_id')
                        ->find($order_id))
            return $this->error('订单不存在');
        $orderModel             = $orderModel->append(['pay_type_text', 'store_order_status_text']);//状态说明
        $orderModel->count_down = 0;                                                                //倒计时
        if ($orderModel->order_status == 1) {
            $orderModel->count_down = strtotime($orderModel->create_time) + config("queue.order.overtime") - time();
        }
        //收货人信息
        $orderModel->store_user = $orderModel->storeUser()
                                             ->field('real_name,mobile')
                                             ->find();
        //收货地址
        $orderModel->address = $orderModel->store()
                                          ->value('address');
        //商品信息
        $field               = 'id,goods_id,goods_rule_id,money,quantity,amount,is_send';
        $orderModel->details = $orderModel->storeOrderDetails()
                                          ->field($field)
                                          ->select()
                                          ->each(function ($item) use ($orderModel){
                                              $item->goods_name  = $item->goods()
                                                                        ->withTrashed()
                                                                        ->value('name');
                                              $item->goods_image = $item->goodsRule()
                                                                        ->withTrashed()
                                                                        ->value('img');
                                              $item->spec_name   = $item->goodsRule()
                                                                        ->withTrashed()
                                                                        ->value('spec_name');
                                                                        
                                            $changeLog = CompanyGoodsChangeLog::field('old_money')
                                                        ->where('store_id', $orderModel->store_id)
                                                        ->where('goods_rule_id', $item->goods_rule_id)
                                                        ->where('store_user_id', $this->user_id)
                                                        ->order('id desc')
                                                        ->find();
                                            if($changeLog){
                                                $item->old_money = $changeLog['old_money'];
                                            }
                                          });
        //业务员信息
        if ($orderModel->salesman_id) {
            $orderModel->salesman = StoreUser::where('id', $orderModel->salesman_id)
                                             ->field('real_name,mobile')
                                             ->find();
        }
        //大额转账信息
        if (in_array($orderModel->pay_type, [3, 5])) {
            $orderModel->large = config('platform.large');
        }
        // 门店信息
        $orderModel->store = $orderModel->store()->find();
        return $this->success('请求成功', compact('orderModel'));
    }


    /**
     * 支付
     * @return Response
     */
    public function pay(): Response
    {
        $param = request()->param();
        $this->model->startTrans();
        try {
            //1. 验证订单
            if (!$orderModel = $this->model->find($param['order_id'])) exception('订单不存在');
            if ($orderModel->order_status >= 2) exception('订单已支付');
            //获取订单金额
            $money = $orderModel->storeOrderDetails()
                                ->sum('amount');
            //余额支付 后期有时间可以写为一个类,方便扩展
            if (request()->post('pay_type') == 4) {
                //验证密码 目前产品没有支付密码
                //验证余额
                $amount = $this->userInfo->storeUserAccountO()
                                         ->find();
                if ($amount->money < $money) exception('余额不足');
                //扣除余额
                $amount->inc('money', -$money)
                       ->save();
                //添加日志记录
                StoreUserAccountDetail::add($this->userInfo->id, $amount->id, $money);
            }
            //账期支付 后期有时间可以写为一个类,方便扩展
            if (request()->post('pay_type') == 3) {
                //是否开启账期
                if ($orderModel->store()
                               ->value('is_on_credit') != 1) exception('账期未开启');
                //设置订单账期支付状态为未出账单
                $orderModel->credit_status = 1;
                //添加账单 并扔进延迟队列
                StoreUserCredit::add($orderModel);
            }
            //大额支付 后期有时间可以写为一个类,方便扩展
            if (request()->post('pay_type') == 5 && !request()->post('voucher', '')) {
                exception('支付凭证不能为空');
            }

            //支付成功
            $orderModel->voucher      = request()->post('voucher', '');
            $orderModel->pay_type     = request()->post('pay_type');
            $orderModel->order_status = 2;//待发货
            $orderModel->save();
            //添加支付日志
            StoreOrderLog::add($orderModel->id, 2);
            //扣减数据库库存 后台发货后扣除
            //分润 后台发货后扣除
            $this->model->commit();
            return $this->success('支付成功');
        } catch (\Exception $e) {
            $this->model->rollback();
            return $this->error($e->getMessage());
        }
    }

    public function salesmanPay()
    {
        $param = request()->param();
        $this->model->startTrans();
        try {
            $orderList = Cache::get($param['unique']);
            if (!$orderList) exception('订单不存在');
            if ($this->userInfo->is_salesman != 1) exception('您不是业务员！');
            // 创建业务员订单
            $salesmanOrder                = new StoreSalesmanOrder();
            $salesmanOrder->store_user_id = $this->store_user_id;
            $salesmanOrder->company_id    = $this->company_id;
            $salesmanOrder->no            = "YW" . date('YmdHis') . mt_rand(100000, 999999);
            $salesmanOrder->pay_type      = $param['pay_type'];
            $salesmanOrder->voucher       = $param['voucher'];
            $salesmanOrder->amount        = $orderList['total_amount'];
            $salesmanOrder->pay_amount    = $orderList['total_amount'];
            $salesmanOrder->save();
            // 判定库存
            $checkGoodsData = [];
            foreach($orderList['order'] as $order){
                foreach($order['goods'] as $goods){
                    if(!isset($checkGoodsData[$goods['goods_rule_id']])){
                        $checkGoodsData[$goods['goods_rule_id']] = [
                            'goods_rule_id' => $goods['goods_rule_id'],
                            'quantity' => $goods['quantity'],
                            'name' => $goods['goods_name'].'--'.$goods['spec_name'],
                        ];
                    }else{
                        $checkGoodsData[$goods['goods_rule_id']]['quantity'] += $goods['quantity'];
                    }
                }
            }
            $res = $this->checkStorage($checkGoodsData);
            if(!$res['code']) exception($res['msg']);
            //订单创建
            $cartIds = '';
            foreach ($orderList['order'] as $order) {
                if(isset($order['cart_ids'])){
                    $cartIds .= $order['cart_ids'] . ',';
                }
                $model  = new StoreOrderModel();
                $model->store_id      = $order['store_id'];
                $model->pay_type      = $param['pay_type'];
                $model->voucher       = $param['voucher'];
                $model->store_user_id = $this->store_user_id;
                $model->salesman_id   = $this->user_id;
                $model->save();

                // 业务员订单关系表
                $salesmanOrderLog = new StoreSalesmanOrderLog();
                $salesmanOrderLog->store_salesman_order_id = $salesmanOrder->id;
                $salesmanOrderLog->store_order_id          = $model->id;
                $salesmanOrderLog->save();

                // 订单详情
                array_walk($order['goods'], function (&$goods) use ($model) {
                    $goods['store_order_id'] = $model->id;
                    $goods['store_user_id']  = $this->store_user_id;
                });

                (new StoreOrderDetail())->saveAll($order['goods']);
//                StoreOrderLog::add($this->model->id, 1);
                StoreOrderLog::add($model->id, 1);
            }
            $res = [];
            // 微信支付
            if ($param['pay_type'] == 2) {
                $res = $this->getWechatPay($salesmanOrder->pay_amount,$salesmanOrder->no,$salesmanOrder->id);
            }
            // 帐期支付
            if ($param['pay_type'] == 3) {
                //是否开启账期 TODO 暂不支持帐期支付
                exception('账期未开启');
            }
            if($param['pay_type'] == 4){
                $amount = $this->userInfo->storeUserAccountO()->find();
                if ($amount->money < $salesmanOrder->pay_amount) exception('余额不足');
                //扣除余额
                $amount->money -= $salesmanOrder->pay_amount;
                $amount->save();
            }
            //大额支付 后期有时间可以写为一个类,方便扩展
            if (request()->post('pay_type') == 5 && !request()->post('voucher', '')) {
                exception('支付凭证不能为空');
            }

            // 更改订单状态
            $salesmanOrder->order_status = 2;
            $salesmanOrder->save();
            $storeOrderIds = StoreSalesmanOrderLog::where('store_salesman_order_id', $salesmanOrder->id)->column('store_order_id');
            StoreOrderModel::whereIn('id',$storeOrderIds)->update(['order_status'=>2]);

            if($cartIds){
                $cartIds = rtrim($cartIds,',');
                StoreCart::destroy(explode(',', $cartIds));//删除购物车
            }
            $this->model->commit();
            return $this->success('下单成功', $res);
        } catch (Exception $e) {
            $this->model->rollback();
            return $this->error($e->getMessage());
        }
    }


    /**
     * @return $this
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     * @throws Exception
     */
    public function addOrder(): static
    {
        //业务员下单
        if ($this->userInfo->is_salesman == 1) {
            //验证门店
            if (!$storeId = request()->param('store_id', '')) exception('门店不能为空');
            //验证门店是否属于业务员
            $store = Store::where('id', $storeId)
                          ->where('salesman_id', $this->user_id)
                          ->find();
            if (!$store) exception('门店不存在或不属于业务员');
            $this->store_user_id      = $store->storeUsers()
                                              ->value('id');//默认取第一个 后期有变动可以调整
            $this->store_id           = $storeId;
            $this->model->salesman_id = $this->user_id;
        }
        $this->model->store_id      = $this->store_id;
        $this->model->pay_type      = request()->param('pay_type', 1);
        $this->model->store_user_id = $this->store_user_id;
        $this->model->save();
        StoreOrderLog::add($this->model->id, 1);
        return $this;
    }

    /**
     * 添加明细
     * @return $this
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     * @throws Exception
     */
    public function addOrderDetail(): static
    {
        //来源:购物车
        if ($cart_ids = request()->param('cart_ids', '')) {
            $carts = StoreCart::whereIn('id', $cart_ids)
                              ->select()
                              ->each(function ($item) {
                                  unset($item->id, $item->create_time, $item->update_time, $item->delete_time, $item->status);
                                  $item->store_order_id = $this->model->id;
                                  $item->store_user_id  = $this->store_user_id;//替换下单人
                                  $this->goodsArray[]   =
                                      ['goods_rule_id' => $item->goods_rule_id, "goods_id" => $item->goods_id,
                                       'quantity'      => $item->quantity];

                                  $item->goods_cate_id = Goods::where('id', $item->goods_id)
                                                              ->withTrashed()
                                                              ->value('goods_cate_id');;//商品分类
                                  $this->checkGoodsAuth($item->goods_rule_id);          //验证是否有商品权限
                              });
            if ($carts->isEmpty()) exception('购物车为空');
            (new StoreOrderDetail())->saveAll($carts->toArray());//添加明细
            StoreCart::destroy(explode(',', $cart_ids));         //删除购物车
        }
        //来源:立即购买
        if ($goods_rule = request()->param('goods_rules', '')) {
            $rule = CompanyGoodsRule::gs()
                                    ->where('goods_rule_id', $goods_rule['goods_rule_id'])
                                    ->find();
            if (!$rule) exception('商品规格不存在');
            $detail                   = new StoreOrderDetail();
            $detail->store_user_id    = $this->store_user_id;
            $detail->store_order_id   = $this->model->id;
            $detail->goods_id         = $rule->goods_id;
            $detail->goods_cate_id    = Goods::where('id', $rule->goods_id)
                                             ->withTrashed()
                                             ->value('goods_cate_id');
            $detail->goods_rule_id    = $rule->goods_rule_id;
            $detail->quantity         = $goods_rule['quantity'];
            $detail->money            = $rule->money;
            $detail->amount           = $rule->money * $goods_rule['quantity'];
            $detail->purchasing_price = $rule->goodsRule()
                                             ->value('purchasing_price');
            $detail->save();

            $goods_rule['goods_id'] = $rule->goods_id;
            $this->goodsArray[]     = $goods_rule;
            $this->checkGoodsAuth($rule->goods_rule_id);//验证是否有商品权限
        }
        //来源:待支付订单 暂时不需要任何操作
        if ($order_id = request()->param('order_id', '')) {

        }
        if (!$cart_ids && !$goods_rule && !$order_id) exception('参数错误');
        return $this;
    }

    /**
     * 验证是否有商品权限
     * @param $goods_rule_id
     * @return void
     * @throws Exception
     */
    public function checkGoodsAuth($goods_rule_id): void
    {
        if ($storeId = request()->param('store_id', '')) {
            //获取门店所属经销商
            $supplier_id = StoreSupplier::storeId($storeId)
                                        ->column('supplier_id');
            $supplier_id = array_unique($supplier_id);
            if (!CompanyOrderDetail::gs($this->company_id)
                                   ->goodsRuleId($goods_rule_id)
                                   ->whereIn('supplier_id', $supplier_id)
                                   ->count()) {
                exception('该商品没有权限购买');//商品数据权限
            };
        }
    }

    private function getWechatPay(mixed $pay_amount,$no,$order_id)
    {
        //微信支付配置
        $config = getWxConfig(['appid' => $this->appid]);
        // 4. 组装支付参数
        $total  = $pay_amount;
        $result = Order::instance($config)
                       ->create('jsapi', [
                           'appid'        => $config['appid'],
                           'mchid'        => $config['mch_id'],
                           'description'  => '商品描述',//商品描述
                           'out_trade_no' => $no,//订单号
                           'notify_url'   => config('platform.notify_url'),//回调地址
                           //用户openid 唯一标识
                           'payer'        => ['openid' => $this->userInfo->storeUserOauths()
                                                                         ->where('oauth_type', 1)
                                                                         ->value('oauth_id')],
                           'amount'       => ['total' => (int)$total, 'currency' => 'CNY'],//total 总金额 单位分
                       ]);

        //延迟队列 10分钟后未支付自动取消订单
        Queue::later(config('queue.order.overtime'), Overtime::class, ["order_id" => $order_id,"order_type"=>1], "overtime");
        return compact('result', 'order_id');

    }

    /**
     * 检查库存
     * Summary of checkStorage
     * @param mixed $goods
     * @return array
     */
    private function checkStorage($goods)
    {
        $returnMsg = '';
        $returnData = [
            'code' => true,
            'msg' => '',
        ];
        // 验证库存
        foreach($goods as $goodsRule){
            $storage = CompanyOrderStorage::goodsRuleId($goodsRule['goods_rule_id'])->gs($this->company_id)->sum('quantity') ?? 0;
            if($goodsRule['quantity'] > $storage){
                $returnMsg .= $goodsRule['name'].'库存不足;';
                $returnData['code'] = false;
            }
        }
        $returnData['msg'] = $returnMsg;
        return $returnData;
    }
}